package org.jeecg.tender.keywordsExtraction.service.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sun.jna.NativeLibrary;
import lombok.extern.slf4j.Slf4j;
import net.sourceforge.tess4j.ITesseract;
import net.sourceforge.tess4j.Tesseract;
import org.apache.commons.lang.StringUtils;
import org.jeecg.attachment.entity.SysAttachment;
import org.jeecg.attachment.service.ISysAttachmentService;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.SftpUtil;
import org.jeecg.config.props.SftpConfig;
import org.jeecg.tender.constant.PublishTypeEnum;
import org.jeecg.tender.constant.SysSwitchConfigConstant;
import org.jeecg.tender.information.entity.TenderInformation;
import org.jeecg.tender.information.service.ITenderInformationService;
import org.jeecg.tender.keywordsExtraction.entity.SysSwitchConfig;
import org.jeecg.tender.keywordsExtraction.entity.TenderInformationExtractor;
import org.jeecg.tender.keywordsExtraction.entity.TenderInformationRecord;
import org.jeecg.tender.keywordsExtraction.extractor.InformationExtractor;
import org.jeecg.tender.keywordsExtraction.mapper.TenderInformationExtractorMapper;
import org.jeecg.tender.keywordsExtraction.service.ISysSwitchConfigService;
import org.jeecg.tender.keywordsExtraction.service.ITenderInformationExtractorService;
import org.jeecg.tender.keywordsExtraction.service.ITenderInformationRecordService;
import org.jeecg.tender.keywordsExtraction.vo.TenderInformationExtractorVO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.*;

@Slf4j
@Service
public class TenderInformationExtractorServiceImpl extends ServiceImpl<TenderInformationExtractorMapper, TenderInformationExtractor> implements ITenderInformationExtractorService {

    @Resource
    private ITenderInformationService tenderInformationService;

    @Resource
    private ISysAttachmentService sysAttachmentService;

    @Resource
    private ISysSwitchConfigService sysSwitchConfigService;

    @Resource
    private ITenderInformationRecordService tenderInformationRecordService;

    @Resource
    private SftpConfig sftpConfig;

    @Value("${tender.tesseract.lib-path}")
    private String libPath;

    @Value("${tender.tesseract.data-path}")
    private String dataPath;

    @Value("${tender.tesseract.language}")
    private String language;

    private static final String TESSERACT_LIB_NAME = "tesseract";

    @Override
    public void informationExtractorData() {
        Date startTime;
        Date endTime;
        SysSwitchConfig sysSwitchConfig = sysSwitchConfigService.lambdaQuery().eq(SysSwitchConfig::getSwitchKey, SysSwitchConfigConstant.TENDER_INFORMATION_TIME).one();
        if (sysSwitchConfig != null && StringUtils.isNotBlank(sysSwitchConfig.getSwitchValue())){
            String[] split = sysSwitchConfig.getSwitchValue().split("——");
            startTime = DateUtils.str2Date(split[0], new SimpleDateFormat(DateUtils.DATE_MINUTE_PATTERN));
            endTime = DateUtils.str2Date(split[1], new SimpleDateFormat(DateUtils.DATE_MINUTE_PATTERN));
        }else {
            // 上个月开始结束时间
            startTime = DateUtils.getLastMonthStartMorning();
            endTime = DateUtils.getLastMonthEndMorning();
        }
        List<TenderInformation> tenderInformations = tenderInformationService.getTenderInformationWebsite(startTime, endTime);
        List<TenderInformationExtractor> extractorList = new ArrayList<>();
        List<TenderInformationExtractorVO> extractorVoList = new ArrayList<>();

        if (!CollectionUtils.isEmpty(tenderInformations)){
            SysSwitchConfig TENDER_PROJECT_CODE_REGEX = sysSwitchConfigService.lambdaQuery().eq(SysSwitchConfig::getSwitchKey, SysSwitchConfigConstant.TENDER_PROJECT_CODE_REGEX).one();
            SysSwitchConfig TENDER_AMOUNTS_WITH_TAX_REGEX = sysSwitchConfigService.lambdaQuery().eq(SysSwitchConfig::getSwitchKey, SysSwitchConfigConstant.TENDER_AMOUNTS_WITH_TAX_REGEX).one();
            SysSwitchConfig TENDER_AMOUNTS_WITHOUT_TAX_REGEX = sysSwitchConfigService.lambdaQuery().eq(SysSwitchConfig::getSwitchKey, SysSwitchConfigConstant.TENDER_AMOUNTS_WITHOUT_TAX_REGEX).one();
            SysSwitchConfig TENDER_PROJECT_NAME_REGEX = sysSwitchConfigService.lambdaQuery().eq(SysSwitchConfig::getSwitchKey, SysSwitchConfigConstant.TENDER_PROJECT_NAME_REGEX).one();
            for (TenderInformation tenderInformation : tenderInformations) {
                try {
                    TenderInformationExtractor tenderInformationExtractor = new TenderInformationExtractor();
                    String nameByCode = PublishTypeEnum.getNameByCode(tenderInformation.getPublishType());
                    tenderInformationExtractor.setNoticeType(nameByCode);
                    tenderInformationExtractor.setNoticeTitle(tenderInformation.getTenderTitle());
                    tenderInformationExtractor.setPurchaser(tenderInformation.getBiddingUnit());
                    tenderInformationExtractor.setSupplier(tenderInformation.getBiddingWinner());

                    // 根据不同数据类型进行不同解析
                    String tenderDescType = tenderInformation.getTenderDescType();
                    String tenderDesc = tenderInformation.getTenderDesc();
                    // 图片类型解析
                    if (("image").equals(tenderInformation.getTenderDescType()) && StringUtils.isNotBlank(tenderDesc)){
                        StringBuilder sb = new StringBuilder();
                        List<String> ids = Arrays.asList(tenderDesc.split(","));
                        List<SysAttachment> list = sysAttachmentService.lambdaQuery().in(SysAttachment::getId, ids).list();
                        for (SysAttachment sysAttachment : list) {
                            sb.append(extractFromImage(sysAttachment.getFileUrl(), sysAttachment.getMd5()));
                        }
                        tenderDesc = sb.toString().replaceAll("\\s+", "").replaceAll("[^\\u4e00-\\u9fa5a-zA-Z0-9]", "");
                        log.info("图片解析结果：{}", tenderDesc);
                    }
                    tenderInformationExtractor.setProjectName(InformationExtractor.extractTenderTitle2projectName(tenderInformation.getTenderTitle(), TENDER_PROJECT_NAME_REGEX.getSwitchValue()));
                    tenderInformationExtractor.setProjectCode(InformationExtractor.extractTenderDesc2projectCode(tenderDesc, TENDER_PROJECT_CODE_REGEX.getSwitchValue()));
                    // 金额-含税、不含税
                    Map<String, List<String>> stringListMap = InformationExtractor.extractAmounts(tenderDesc, TENDER_AMOUNTS_WITH_TAX_REGEX.getSwitchValue(), TENDER_AMOUNTS_WITHOUT_TAX_REGEX.getSwitchValue());
                    List<String> withTaxList = stringListMap.get("withTax");
                    if (!CollectionUtils.isEmpty(withTaxList)){
                        tenderInformationExtractor.setAmountWithTax(withTaxList.get(0));
                    }
                    List<String> withoutTaxList = stringListMap.get("withoutTax");
                    if (!CollectionUtils.isEmpty(withoutTaxList)){
                        tenderInformationExtractor.setAmountWithoutTax(withoutTaxList.get(0));
                    }
                    tenderInformationExtractor.setCreateTime(new Date());
                    tenderInformationExtractor.setUpdateTime(new Date());
                    tenderInformationExtractor.setTenderInformationId(tenderInformation.getId());
                    tenderInformationExtractor.setInformationDataType(tenderDescType);
                    tenderInformationExtractor.setNoticeUrl(tenderInformation.getWebsiteUrl());
                    // 保存jsonTex文件，同时上传sftp
                    TenderInformationExtractorVO tenderInformationExtractorVO = InformationExtractor.tenderInformationExtractor2TenderInformationExtractorVO(tenderInformationExtractor);
                    extractorVoList.add(tenderInformationExtractorVO);
                    extractorList.add(tenderInformationExtractor);
                }catch (Exception e){
                    log.error("解析数据失败，tenderId：{}", tenderInformation.getId(), e);
                }
            }
            // 保存数据
            if (extractorList.size() > 0){
                // 文件上传
                Result<Long> longResult = sysAttachmentService.uploadTendFile(JSONUtil.toJsonStr(extractorVoList), DateUtils.formatDate(startTime,DateUtils.DATE_NUM_PATTERN), DateUtils.formatDate(endTime,DateUtils.DATE_NUM_PATTERN));
                if (longResult.isSuccess()){
                    extractorList.forEach(item -> {item.setSysAttachmentId(longResult.getResult().intValue());});
                    // 保存记录
                    TenderInformationRecord tenderInformationRecord = new TenderInformationRecord();
                    tenderInformationRecord.setStartTime(DateUtils.formatDate(startTime,DateUtils.DATE_NUM_PATTERN));
                    tenderInformationRecord.setEndTime(DateUtils.formatDate(endTime,DateUtils.DATE_NUM_PATTERN));
                    tenderInformationRecord.setSysAttachmentId(longResult.getResult().intValue());
                    tenderInformationRecord.setCreateDatetime(new Date());
                    tenderInformationRecord.setUpdateDatetime(new Date());
                    tenderInformationRecordService.save(tenderInformationRecord);

                }
                this.saveBatch(extractorList);
            }
        }
    }

    @Override
    public String extractFromImage(String directory, String sftpFileName) {
        SftpUtil downloadSftp = null;
        try {
            downloadSftp = SftpUtil.getInstance(sftpConfig.getTenderSftpConfig());
            InputStream inputStream = downloadSftp.download(directory, sftpFileName);
            BufferedImage image = ImageIO.read(inputStream);
            NativeLibrary.addSearchPath(TESSERACT_LIB_NAME, libPath);
            ITesseract tesseract = new Tesseract();
            // 设置训练数据目录，需要自行下载tessdata
            tesseract.setDatapath(dataPath);
            tesseract.setLanguage(language); // 支持中英文
            String text = tesseract.doOCR(image);
            return text;
        }catch (Exception e){
            log.error("解析图片失败，directory：{}，sftpFileName：{}", directory, sftpFileName, e);
            return null;
        }
    }
}
